'use strict'

const { homedir } = require('os')
const path = require('path')
const inquirer = require('inquirer')
const fse = require('fs-extra')
const semver = require('semver')
const Command = require('@imooc-yishen-cli-dev/command')
const Package = require('@imooc-yishen-cli-dev/package')
const log = require('@imooc-yishen-cli-dev/log')
const { spinnerStart, sleep } = require('@imooc-yishen-cli-dev/utils')
const getProjectTemplate = require('./getProjectTemplate')

const TYPE_PROJECT = 'project'
const TYPE_COMPONENT = 'component'

const TEMPLATE_TYPE_NORMAL = 'normal'
const TEMPLATE_TYPE_CUSTOM = 'custom'

const prompt = inquirer.createPromptModule()

class InitCommand extends Command {
  init() {
    this.projectName = this._argv[0] || ''
    this.force = this._argv[1]?.force
    log.verbose('projectName', this.projectName)
    log.verbose('force', this.force)
  }
  async exec() {
    const projectInfo = await this.prepare()
    if (projectInfo) {
      log.verbose('projectInfo', projectInfo)
      this.projectInfo = projectInfo
      // 下载模板
      await this.downloadTemplate()
      // 安装模板
      await this.installTemplate()
    }
  }

  async prepare() {
    // 0. 判断项目模板是否存在
    const template = await getProjectTemplate()
    if (!template || template.length === 0) {
      throw new Error('项目模板不存在')
    }
    this.template = template
    // 1. 判断当前目录是否为空
    const localPath = process.cwd()
    if (!this.isDirEmpty(localPath)) {
      let ifContinue = false
      if (!this.force) {
        // 询问是否继续创建
        ifContinue = (
          await prompt({
            type: 'confirm',
            name: 'ifContinue',
            default: false,
            message: '当前文件夹不为空，是否继续创建项目？',
          })
        ).ifContinue
        if (!ifContinue) {
          return
        }
      }
      // 2. 是否启动强制更新
      if (ifContinue || this.force) {
        // 给用户做二次确认
        const { confirmDelete } = await prompt({
          type: 'confirm',
          name: 'confirmDelete',
          default: false,
          message: '是否确认清空当前目录下的文件？',
        })
        if (confirmDelete) {
          // 清空当前目录
          fse.emptyDirSync(localPath)
        }
      }
    }
    return this.getProjectInfo()
  }

  async getProjectInfo() {
    let projectInfo = {}
    // 选择创建项目或组件
    const { type } = await prompt({
      type: 'list',
      name: 'type',
      message: '请选择初始化类型?',
      default: TYPE_PROJECT,
      choices: [
        { value: TYPE_PROJECT, name: '项目' },
        { value: TYPE_COMPONENT, name: '组件' },
      ],
    })
    if (type === TYPE_PROJECT) {
      // 获取项目的基本信息
      const project = await prompt([
        {
          type: 'input',
          name: 'projectName',
          message: '请输入项目名称',
          // TODO 测试时default 设置为q1,上线前记得修改为空
          default: 'q1',
          validate: function (v) {
            const done = this.async()
            setTimeout(function () {
              if (
                !/^[a-zA-Z]+([-][a-zA-Z0-9][a-zA-Z0-9]*|[_][a-zA-Z0-9][a-zA-Z0-9]*|[a-zA-Z0-9])*$/.test(
                  v
                )
              ) {
                done('请输入合法的项目名称')
                return
              }
              done(null, true)
            }, 0)

            // 首字符必须为英文字符
            // 尾字符必须为英文或数字，不能为字符
            // 字符仅允许“-_”
            return /^[a-zA-Z]+([-][a-zA-Z0-9][a-zA-Z0-9]*|[_][a-zA-Z0-9][a-zA-Z0-9]*|[a-zA-Z0-9])*$/.test(
              v
            )
          },
          filter: function (v) {
            return v
          },
        },
        {
          type: 'input',
          name: 'projectVersion',
          message: '请输入项目版本号',
          default: '1.0.0',
          validate: function (v) {
            const done = this.async()
            setTimeout(function () {
              if (!semver.valid(v)) {
                done('请输入合法的项目名称')
                return
              }
              done(null, true)
            }, 0)
            return !!semver.valid(v)
          },
          filter: function (v) {
            if (!!semver.valid(v)) {
              return semver.valid(v)
            } else {
              return v
            }
          },
        },
        {
          type: 'list',
          name: 'projectTemplate',
          message: '请选择初始化项目模板',
          choices: this.createTemplateChoices(),
        },
      ])
      projectInfo = {
        type,
        ...project,
      }
    } else if (type === TYPE_COMPONENT) {
    }
    return projectInfo
    // return 项目的基本信息 object
  }

  async downloadTemplate() {
    const templateInfo = this.template.find(
      (item) => item.npmName === this.projectInfo.projectTemplate
    )
    this.templateInfo = templateInfo
    const targetPath = path.resolve(homedir(), '.imooc-cli-dev', 'template')
    const storeDir = path.resolve(
      homedir(),
      '.imooc-cli-dev',
      'template',
      'node_modules'
    )
    const templateNpm = new Package({
      targetPath,
      storeDir,
      packageName: templateInfo.npmName,
      packageVersion: templateInfo.version,
    })
    if (await templateNpm.exists()) {
      const spinner = spinnerStart('正在更新模板..')
      try {
        await templateNpm.update()
        log.success('更新模板成功！')
        this.templateNpm = templateNpm
      } catch (error) {
        throw error
      } finally {
        spinner.stop(true)
      }
      spinner.stop(true)
    } else {
      const spinner = spinnerStart('正在下载模板..')
      try {
        await templateNpm.install()
        log.success('下载模板成功！')
        this.templateNpm = templateNpm
      } catch (error) {
        throw error
      } finally {
        spinner.stop(true)
      }
    }
  }

  async installTemplate() {
    if (this.templateInfo) {
      if (!this.templateInfo.type) {
        this.templateInfo.type === TEMPLATE_TYPE_NORMAL
      }
      if (this.templateInfo.type === TEMPLATE_TYPE_NORMAL) {
        // 标准安装
        await this.installNormalTemPlate()
      } else if (this.templateInfo.type === TEMPLATE_TYPE_CUSTOM) {
        // 自定义安装
        await this.installCustomTemPlate()
      } else {
        throw new Error('无法识别项目模板信息！')
      }
    } else {
      throw new Error('项目信息不存在！')
    }
  }

  async installNormalTemPlate() {
    console.log('正常安装', this.templateNpm.cacheFilePath)
    // 拷贝模板代码至当前目录
    const templatePath = path.resolve(
      this.templateNpm.cacheFilePath,
      'template'
    )
    const targetPath = process.cwd()
    fse.ensureDirSync(templatePath)
    fse.ensureDirSync(targetPath)
    fse.copySync(templatePath, targetPath)
    // 依赖安装
    // 启动命令执行
  }
  async installCustomTemPlate() {
    console.log('自定义安装', this.templateNpm)
  }

  isDirEmpty(localPath) {
    let fileList = fs.readdirSync(localPath)
    // 文件过滤的逻辑
    fileList = fileList.filter(
      (file) => !file.startsWith('.') && ['node_modules'].indexOf(file) < 0
    )
    return !fileList || fileList.length <= 0
  }

  createTemplateChoices() {
    return this.template.map((item) => ({
      value: item.npmName,
      name: item.name,
    }))
  }
}

function init(argv) {
  return new InitCommand(argv)
}

module.exports = init
module.exports.InitCommand = InitCommand
